package com.wolfking.converter.transform.base;


import com.google.common.collect.Sets;
import com.wolfking.converter.transform.FieldTransform;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.time.*;
import java.util.Date;
import java.util.Set;
import java.util.regex.Pattern;

@Slf4j
public class DateFieldTransform implements FieldTransform<Date> {

    private final Set<Class<?>> classes = Sets.newHashSet(Long.class, long.class);

    private String format = "";
    private static final Set<String> formats = Sets.newHashSet(
            "yyyy-MM-dd HH:mm:ss.SSS",
            "yyyy-MM-dd HH:mm:ss",
            "yyyy-MM-dd HH:mm",
            "yyyy-MM-dd",
            "yyyyMMdd",
            "HH:mm:ss"
    );

    public DateFieldTransform() {
    }


    public DateFieldTransform(String format) {
        this.format = format;
    }

    private final Pattern pattern = Pattern.compile("[0-9]*");

    @Synchronized
    public static void registerFormat(String format) {
        formats.add(format);
    }

    @Override
    public boolean canTransform(Class<?> fieldType) {
        return fieldType.equals(Date.class);
    }

    @Override
    public Date transform(Object value) {
        if (classes.contains(value.getClass())) {
            return new Date((Long) value);
        }
        if (value instanceof LocalDateTime) {
            ZoneId zoneId = ZoneId.systemDefault();
            ZonedDateTime zonedDateTime = ((LocalDateTime) value).atZone(zoneId);
            Instant instant = zonedDateTime.toInstant();
            return Date.from(instant);
        }
        if (value instanceof LocalDate) {
            ZoneId zoneId = ZoneId.systemDefault();
            ZonedDateTime zonedDateTime = LocalDateTime.of((LocalDate) value, LocalTime.MIN).atZone(zoneId);
            Instant instant = zonedDateTime.toInstant();
            return Date.from(instant);
        }

        try {
            String[] array = formats.toArray(new String[]{});
            if (StringUtils.isNotBlank(this.format)) {
                array = new String[]{format};
            }
            return DateUtils.parseDate(value.toString().trim(), array);
        } catch (Exception e) {
            log.debug("", e);
        }
        try {
            String toString = value.toString().trim();
            if (pattern.matcher(toString).matches()) {
                return new Date(Long.parseLong(toString));
            }
        } catch (Exception e) {
            log.debug("", e);
        }
        throw new IllegalStateException(String.format("date[%s]换换异常", value.toString()));
    }
}
